// 版权所有 Epic Games, Inc. 保留所有权利。

#pragma once

#include "GameplayTagContainer.h"
#include "Net/Serialization/FastArraySerializer.h"

#include "GameplayTagStack.generated.h"

struct FGameplayTagStackContainer;
struct FNetDeltaSerializeInfo;

/**
 * 表示一个游戏标签堆栈（标签 + 数量）
 */
USTRUCT(BlueprintType)
struct FGameplayTagStack : public FFastArraySerializerItem
{
	GENERATED_BODY()

	FGameplayTagStack()
	{}

	FGameplayTagStack(FGameplayTag InTag, int32 InStackCount)
		: Tag(InTag)
		, StackCount(InStackCount)
	{
	}

	FString GetDebugString() const;

private:
	friend FGameplayTagStackContainer;

	UPROPERTY()
	FGameplayTag Tag; // 游戏标签

	UPROPERTY()
	int32 StackCount = 0; // 堆栈数量
};

/** 游戏标签堆栈容器 */
USTRUCT(BlueprintType)
struct FGameplayTagStackContainer : public FFastArraySerializer
{
	GENERATED_BODY()

	FGameplayTagStackContainer()
	//	: Owner(nullptr)
	{
	}

public:
	/**
	 * 向标签添加指定数量的堆栈（如果StackCount低于1则不执行任何操作）
	 */
	void AddStack(FGameplayTag Tag, int32 StackCount);

	/**
	 * 从标签移除指定数量的堆栈（如果StackCount低于1则不执行任何操作）
	 */
	void RemoveStack(FGameplayTag Tag, int32 StackCount);

	/**
	 * 返回指定标签的堆栈数量（如果标签不存在则返回0）
	 */
	int32 GetStackCount(FGameplayTag Tag) const
	{
		return TagToCountMap.FindRef(Tag);
	}

	/**
	 * 如果存在至少一个指定标签的堆栈则返回true
	 */
	bool ContainsTag(FGameplayTag Tag) const
	{
		return TagToCountMap.Contains(Tag);
	}

	//~FFastArraySerializer 契约
	void PreReplicatedRemove(const TArrayView<int32> RemovedIndices, int32 FinalSize);
	void PostReplicatedAdd(const TArrayView<int32> AddedIndices, int32 FinalSize);
	void PostReplicatedChange(const TArrayView<int32> ChangedIndices, int32 FinalSize);
	//~FFastArraySerializer 契约结束

	bool NetDeltaSerialize(FNetDeltaSerializeInfo& DeltaParms)
	{
		return FFastArraySerializer::FastArrayDeltaSerialize<FGameplayTagStack, FGameplayTagStackContainer>(Stacks, DeltaParms, *this);
	}

private:
	// 复制的游戏标签堆栈列表
	UPROPERTY()
	TArray<FGameplayTagStack> Stacks;
	
	// 用于查询的加速标签堆栈列表
	TMap<FGameplayTag, int32> TagToCountMap;
};

template<>
struct TStructOpsTypeTraits<FGameplayTagStackContainer> : public TStructOpsTypeTraitsBase2<FGameplayTagStackContainer>
{
	enum
	{
		WithNetDeltaSerializer = true, // 支持网络增量序列化
	};
};